using System;
using System.Collections.Generic;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model.Core;
using DevExpress.ExpressApp.Model.NodeGenerators;
using DevExpress.ExpressApp.Utils;

namespace FeatureCenter.Module.Actions {
    public class CustomDetailViewItemsGenarator : ModelNodesGeneratorUpdater<ModelDetailViewItemsNodesGenerator> {
        public const string GeneralId = "General";
        public const string MainTabId = "MainTab";
        public const string FooterId = "Footer";
        public const string TabPageNameAttribute = "TabPageName";
        public const string VisiblePropertiesAttribute = "VisibleProperties";
        public const string FooterAttribute = "Footer";
        public const string TabPageIdAttribute = "TabPageId";

        public override void UpdateNode(ModelNode node) {
            if(node.Parent is IModelDetailView && ((IModelDetailView)(node.Parent)).ModelClass.TypeInfo.Implements<ICustomLayoutInfo>()) {
                GenerateCustomLayout((IModelDetailView)node.Parent);
            }
        }

        private static ModelDefaultAttribute FindModelDefaultAttribute(IMemberInfo memberInfo, string attributeName) {
            foreach(ModelDefaultAttribute modelDefaultAttribute in memberInfo.FindAttributes<ModelDefaultAttribute>()) {
                if(modelDefaultAttribute.PropertyName == attributeName) {
                    return modelDefaultAttribute;
                }
            }
            return null;
        }
        private void GenerateCustomLayout(IModelDetailView modelDetailView) {
            ITypeInfo iTypeInfo = modelDetailView.ModelClass.TypeInfo;
            foreach(IModelViewItem item in modelDetailView.Items) {
                IModelPropertyEditor editorInfo = (IModelPropertyEditor)item;
                if(FindModelDefaultAttribute(editorInfo.ModelMember.MemberInfo, VisiblePropertiesAttribute) != null) {
                    editorInfo.PropertyEditorType = typeof(DetailPropertyEditor);// editorInfo.ModelMember.EditorsInfo[EditorAliases.DetailPropertyEditor].DefaultEditor;
                }
                string visiblePropertiesAttributeValue = ((IModelClassMemberExtender)item).VisibleProperties;
                if(editorInfo.PropertyEditorType == typeof(DetailPropertyEditor) && !string.IsNullOrEmpty(visiblePropertiesAttributeValue)) {
                    string[] visibleProperties = visiblePropertiesAttributeValue.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    string nestedViewId = iTypeInfo.Name + "_" + editorInfo.PropertyName + "_DetailView";

                    GenerateNestedDetailView(modelDetailView.Application.Views, nestedViewId, editorInfo.ModelMember.Type.FullName, visibleProperties);
                    editorInfo.View = modelDetailView.Application.Views[nestedViewId];
                }
            }
        }
        private void GenerateNestedDetailView(IModelViews views, string nestedViewId, string nestedClassFullName, string[] visibleProperties) {
            IModelDetailView detailViewInfo = views.AddNode<IModelDetailView>(nestedViewId);
            IModelClass modelClass = views.Application.BOModel[nestedClassFullName];
            if(modelClass == null) {
                modelClass = views.Application.BOModel.AddNode<IModelClass>(nestedClassFullName);
                ITypeInfo typeInfo = XafTypesInfo.Instance.FindTypeInfo(nestedClassFullName);
                modelClass.SetValue<ITypeInfo>("TypeInfo", typeInfo);
            }
            detailViewInfo.ModelClass = modelClass;

            List<IModelViewItem> items = new List<IModelViewItem>();
            foreach(IModelViewItem item in detailViewInfo.Items) {
                items.Add(item);
            }
            foreach(IModelViewItem itemR in items) {
                itemR.Remove();
            }

            int index = 0;
            foreach(string propertyName in visibleProperties) {
                if(modelClass.AllMembers[propertyName] == null) {   // T7462
                    modelClass.OwnMembers.AddNode<IModelMember>(propertyName);
                }
                IMemberInfo memberInfo = modelClass.AllMembers[propertyName].MemberInfo;
                IModelPropertyEditor editor = detailViewInfo.Items.AddNode<IModelPropertyEditor>(propertyName);
                editor.ImmediatePostData = true;
                editor.Index = index++;
                editor.PropertyName = propertyName;
    
                if(string.IsNullOrEmpty(((IModelViewItem)editor).Caption)) {
                    ((IModelViewItem)editor).Caption = CaptionHelper.ConvertCompoundName(propertyName);
                }
            }
        }
    }
    public interface IModelClassMemberExtender {
        string TabPageName { get; set; }
        bool Footer { get; set; }
        string VisibleProperties { get; set; }
    }
    public interface IModelLayoutGroupExtender {
        string TabPageId { get; set; }
    }
    [ModelInterfaceImplementor(typeof(IModelClassMemberExtender), "ModelMember")]
    public interface IModelPropertyEditorClassMemberExtender : IModelClassMemberExtender { }
}
